package com.jsbs.iam.component.filter;

import com.jsbs.iam.component.constant.Constants;
import com.jsbs.iam.component.dto.IamAuthDto;
import com.jsbs.iam.component.dto.Result;
import com.jsbs.iam.component.utils.HttpUtil;
import com.jsbs.iam.component.utils.Json;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 权限认证过滤器
 * 
 * @author junwc
 */
@Component
public class AuthorityFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(AuthorityFilter.class);

    /**
     * 权限认证白名单
     */
    @Value("${iam.auth.white.url}")
    private String whiteUrl;

    /**
     * 权限接入标识
     */
    @Value("${iam.auth.access.flag}")
    private boolean authAccessFlag;

    /**
     * IAM权限中心域名
     */
    @Value("${iam.auth.domain}")
    private String iamAuthDomain;

    /**
     * IAM权限中心鉴权请求URL地址
     */
    @Value("${iam.auth.url}")
    private String iamAuthUrl;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String url = request.getRequestURI();
        log.info("authority filter for requestURL: {}", url);
        // 是否接入权限中心 true是 false否
        if (authAccessFlag) {
            // 白名单
            List<String> whiteUrlList = new ArrayList<>();
            if (StringUtils.isNotEmpty(whiteUrl)) {
                whiteUrlList = Arrays.asList(whiteUrl.split(","));
            }
            // 白名单为空 或 当前URL非白名单 则需要进行权限认证请求转发至IAM权限认证接口
            if (CollectionUtils.isEmpty(whiteUrlList) || !whiteUrlList.contains(url)) {
                IamAuthDto iamAuthDto = new IamAuthDto();
                // 用户编码
                iamAuthDto.setUserCode(request.getHeader(Constants.USER_CODE));
                // 归属租户
                iamAuthDto.setCompanyCode(request.getHeader(Constants.COMPANY_CODE));
                // 服务域名
                iamAuthDto.setServerName(request.getServerName());
                // 请求URL
                iamAuthDto.setUrl(request.getRequestURI());
                // 用户类型
                String userType = request.getHeader(Constants.USER_TYPE);
                // 默认为普通用户
                if (StringUtils.isEmpty(userType)) {
                    userType = Constants.USER_TYPE_NOMAL;
                }
                // 管理员角色编码
                String adminRoleCode = request.getHeader(Constants.ADMIN_ROLE_CODE);
                iamAuthDto.setUserType(userType);
                iamAuthDto.setAdminRoleCode(adminRoleCode);
                // 请求权限中心进行统一权限认证
                log.info("Route=>AuthorityFilter method=doFilter 权限认证请求开始，入参：{}", Json.toJsonString(iamAuthDto));
                String resultStr = HttpUtil.postJson(iamAuthDomain + iamAuthUrl, Json.toJsonString(iamAuthDto));
                if (StringUtils.isEmpty(resultStr)) {
                    log.info("Route=>AuthorityFilter method=doFilter 权限认证返回异常，入参：{}", Json.toJsonString(iamAuthDto));
                    throw new RuntimeException("权限认证发生异常");
                }
                log.info("Route=>AuthorityFilter method=doFilter 权限认证返回结果：{}", resultStr);
                Result result = Json.parseJson(resultStr, Result.class);
                // 权限认证失败
                if (!result.isSuccess()) {
                    response.sendError(HttpStatus.SC_FORBIDDEN, "权限认证失败");
                    return;
                }
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}